package com.squid.base.utils;

import com.squid.base.common.error.ExceptionFactory;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 异步工具类
 *
 * @author jh
 * @date 2023/3/24 9:11
 */
public class AsyncUtils {
    /**
     * 异步方法List，且有返回值的，等待全部结束后返回，每个项都会生成一个线程
     *
     * @param list     请求入参
     * @param function 执行的函数 T 请求类型，R 返回类型
     * @param executor 线程池
     * @return {@link CompletableFuture <  List <R>> }
     * @date 2023/03/21 14:57:52
     */

    public static <T, R> CompletableFuture<List<R>> asyncListResult(List<T> list, Function<T, R> function, Executor executor) {
        List<CompletableFuture<R>> collect = list.stream()
                .map(o -> CompletableFuture.supplyAsync(() -> function.apply(o), executor))
                .collect(Collectors.toList());

        CompletableFuture<R>[] futureResultArray = collect.toArray(new CompletableFuture[collect.size()]);
        CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(futureResultArray);
        CompletableFuture<List<R>> listCompletableFuture = combinedFuture
                .thenApply(o -> collect.stream().map(CompletableFuture::join).collect(Collectors.toList()));
        return listCompletableFuture;
    }

    /**
     * 异步方法List，无返回值
     *
     * @param list     请求入参
     * @param function 执行的函数 T
     * @param executor 线程池
     * @date 2023/03/21 14:57:52
     */
    public static <T> void asyncListVoid(List<T> list, Runnable function, Executor executor) {
        list.forEach(o -> CompletableFuture.runAsync(function, executor)
                .exceptionally(throwable -> {
                            throw ExceptionFactory.instanceServerException(throwable.getMessage(), throwable);
                        }
                ));
    }

    /**
     * 异步方法,不需要返回值的
     *
     * @param function 执行的函数
     * @param executor 线程池
     */
    public static void asyncVoid(Runnable function, Executor executor) {
        CompletableFuture.runAsync(function, executor).exceptionally(throwable -> {
            throw ExceptionFactory.instanceServerException(throwable.getMessage(), throwable);
        });
    }

    /**
     * 异步方法,需要返回值的
     *
     * @param function 执行的函数
     * @param executor 线程池
     */
    public static <T, R> CompletableFuture<R> asyncResult(T t, Function<T, R> function, Executor executor) {
        return CompletableFuture.supplyAsync(() -> function.apply(t), executor).exceptionally(throwable -> {
            throw ExceptionFactory.instanceServerException(throwable.getMessage(), throwable);
        });
    }
}
